#include "BAT32G157.h"
#include "userdefine.h"
#include "iica.h"
//#include "system.h"
//#include "log.h"
#include "insdrv_i2c.h"
#include "userdefine.h"
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

//#include <platform/drivers/insdrv_i2c.h>
//#include <platform/drivers/insdrv_timer.h>

#if (PLATFORM_CHIP == PLATFORM_BAT32G157)

int32_t InsDrv_I2c_Init(void)
__ATTRIB_ALIAS__(InsDrv_I2c_BAT32G157_Init);

int32_t InsDrv_I2c_MasterWrite(InsDrv_I2c_Ctrl_t ctrl, uint8_t addr, uint8_t *tx_buf, uint32_t tx_len, uint32_t timeout)
__ATTRIB_ALIAS__(InsDrv_I2c_BAT32G157_MasterWrite);

int32_t InsDrv_I2c_MasterRead(InsDrv_I2c_Ctrl_t ctrl, uint8_t addr, uint8_t *rx_buf, uint32_t rx_len, uint32_t timeout)
__ATTRIB_ALIAS__(InsDrv_I2c_BAT32G157_MasterRead);

int32_t InsDrv_I2c_SetSpeed(InsDrv_I2c_Ctrl_t ctrl, InsDrv_I2c_Speed_e speedmode)
__ATTRIB_ALIAS__(InsDrv_I2c_BAT32G157_SetSpeed);

#define DATA_TRANSLATE_TIMEOUT_CNT		(100)
#define STOP_SIGNAL_TIMEOUT_CNT         (1500)

#define INSDRV_I2C_BAT32G157_ID_NUM   (1)
#define PD_TCPC_I2C_TIMEOUT              (10)

InsDrv_I2c_Ctrl_t s_i2c_ctrl = {INSDRV_I2C1, INSDRV_I2C_SPEED_FAST};

void delay_1us(uint32_t us)
{
    uint32_t t1 = 0, t2 = 0, delta = 0, sysclk = 0;
    uint32_t SystemCoreClock = 48000000U; //48MHz,??????????
    sysclk = SystemCoreClock/1000000;

    t1 = SysTick->VAL;
    while (1) 
    {
        t2 = SysTick->VAL;
        delta = t2 < t1 ? (t1 - t2) : (SysTick->LOAD - t2 + t1) ;
        if (delta >= us * sysclk)
        {
            break;
        }
    }

}

int32_t InsDrv_I2c_BAT32G157_Init()
{
    InsDrv_I2c_Ctrl_t ctrl = s_i2c_ctrl;
    if(ctrl.id > INSDRV_I2C_BAT32G157_ID_NUM)
    {
    	return INSERR_NG;
    }
    if(ctrl.id == INSDRV_I2C0)
    {
        IICA0_Init(IICA_FAST_MODE);
    }
    else if(ctrl.id == INSDRV_I2C1)
    {
        IICA1_Init(IICA_FAST_MODE);
    }
	return INSERR_OK;
}

int32_t InsDrv_I2c_BAT32G157_SetSpeed(InsDrv_I2c_Ctrl_t ctrl, InsDrv_I2c_Speed_e speedmode)
{
	if(ctrl.id == INSDRV_I2C0)
	{
		switch(speedmode)
		{
			case INSDRV_I2C_SPEED_STANDARD:
			{
				IICA0_Init(IICA_STANDARD_MODE);
				break;
			}
			case INSDRV_I2C_SPEED_FAST:
			{
				IICA0_Init(IICA_FAST_MODE);
				break;
			}
			default:break;
		}
	}
    else if(ctrl.id == INSDRV_I2C1)
	{
		switch(speedmode)
		{
			case INSDRV_I2C_SPEED_STANDARD:
			{
				IICA1_Init(IICA_STANDARD_MODE);
				break;
			}
			case INSDRV_I2C_SPEED_FAST:
			{
				IICA1_Init(IICA_FAST_MODE);
				break;
			}
			default:break;
		}
	}
	return INSERR_OK;
}

void InsDrv_I2c_BAT32G157_Reset(InsDrv_I2c_Ctrl_t ctrl)
{
    #if 0
    InsDrv_Timer_DelayMs(10);
    CGC->PER0 |= CGC_PER0_IICA0EN_Msk;              /* enables input clock supply */
    IICA->IICCTL00 = _00_IICA_OPERATION_STOP;       /* stop operation */
    INTC_DisableIRQ(IICA_IRQn);                         /* disable INTIICA interrupt flag */           
    INTC_ClearPendingIRQ(IICA_IRQn);                    /* clear INTIICA interrupt flag */
    IICA->IICF0    |= _01_IICA_RESERVATION_DISABLE;       /* disable communication reservation */
    IICA->IICCTL00 |= _08_IICA_INTERRUPT_REQUEST_NINTH; /* interrupt request is generated at the ninth clock's falling edge */
    IICA->IICCTL00 |= _04_IICA_ACKOWNLEDGMENT_ENABLE;   /* enable acknowledgment */
    IICA->IICCTL00 |= _80_IICA_OPERATION_ENABLE;                /* enable operation */
    IICA->IICCTL00 |= _40_IICA_OPERATION_STANDBY;       /* this exits from the current communications and sets standby mode */
    INTC_EnableIRQ(IICA_IRQn);                          /* enable INTIICA interrupt flag */
    #endif
    if(ctrl.id == INSDRV_I2C0)
    {
        INTC_DisableIRQ(IICA0_IRQn);                         /* disable INTIICA interrupt flag */
        INTC_ClearPendingIRQ(IICA0_IRQn);                    /* clear INTIICA interrupt flag */
        IIC0->IICCTL00 |= _40_IICA_OPERATION_STANDBY;     /* stop communication */
        // while(IICA->IICCTL00 & IICA_IICCTL00_WREL_Msk);
        IIC0->IICCTL00 &= ~IICA0_IICCTL00_IICE_Msk;
        CGC->PER0 &= ~CGC_PER0_IICA0EN_Msk;

        IICA0_Init(IICA_FAST_MODE);

        printf("I2C Reset, busy:%d\r\n", (int)(IIC0->IICF0 & IICA0_IICF0_IICBSY_Msk) >> IICA0_IICF0_IICBSY_Pos);
    }
    else if(ctrl.id == INSDRV_I2C1)
    {
        INTC_DisableIRQ(IICA1_IRQn);                         /* disable INTIICA interrupt flag */
        INTC_ClearPendingIRQ(IICA1_IRQn);                    /* clear INTIICA interrupt flag */
        IIC1->IICCTL10 |= _40_IICA_OPERATION_STANDBY;     /* stop communication */
        // while(IICA->IICCTL00 & IICA_IICCTL00_WREL_Msk);
        IIC1->IICCTL10 &= ~IICA1_IICCTL10_IICE_Msk;
        CGC->PER0 &= ~CGC_PER0_IICA1EN_Msk;

        IICA1_Init(IICA_FAST_MODE);

        printf("I2C Reset, busy:%d\r\n", (int)((IIC1->IICF1 & IICA1_IICF1_IICBSY_Msk) >> IICA1_IICF1_IICBSY_Pos));
    }
    
}

#define SGM_USE_I2C
#ifdef SGM_USE_I2C
int32_t InsDrv_I2c_BAT32G157_MasterWrite(InsDrv_I2c_Ctrl_t ctrl, uint8_t addr, uint8_t *tx_buf, uint32_t tx_len, uint32_t timeout)
{
    
    MD_STATUS status = MD_OK;
    //int i=0;
    
    uint32_t delay = timeout * 5000; //10000
   
    if(ctrl.id > INSDRV_I2C_BAT32G157_ID_NUM)
    {
    	return -1;
    }
    if(ctrl.id == INSDRV_I2C0)        
    {
        status = IICA0_MasterSend(addr, tx_buf, tx_len, 40);
        while(g_iica0_tx_end == 0 && --delay);
        if (delay)
            return status;
        else
            IICA0_StopCondition();
    
    }
    else if (ctrl.id == INSDRV_I2C1)
    {
        status = IICA1_MasterSend(addr, tx_buf, tx_len, 40);
        while(g_iica1_tx_end == 0 && --delay);
        if (delay)
            return status;
        else
            IICA1_StopCondition();
    }   
    
    return status;
}

int32_t InsDrv_I2c_BAT32G157_MasterRead(InsDrv_I2c_Ctrl_t ctrl, uint8_t addr, uint8_t *rx_buf, uint32_t rx_len, uint32_t timeout)
{
    MD_STATUS status = MD_OK;
    uint32_t delay = timeout * 5000; //
    
    
    if(ctrl.id > INSDRV_I2C_BAT32G157_ID_NUM)
    {
    	return -1;
    }
    if(ctrl.id == INSDRV_I2C0)        
    {
        status = IICA0_MasterReceive(addr, rx_buf, rx_len, 40);
        while(g_iica0_rx_end == 0 && --delay);
        if (delay)
            return status;
        else
            IICA0_StopCondition();
    
    }
    else if (ctrl.id == INSDRV_I2C1)
    {
        status = IICA1_MasterReceive(addr, rx_buf, rx_len, 40);
        while(g_iica1_rx_end == 0 && --delay);
        if (delay)
            return status;
        else
            IICA1_StopCondition();    
    }
    return status;
}

int _i2c1_rcv(uint8_t slave_addr, uint8_t reg_addr, uint8_t *dat, uint8_t len)
{
    int ret = 0;
    ret = InsDrv_I2c_MasterWrite(s_i2c_ctrl, slave_addr, &reg_addr, 1, PD_TCPC_I2C_TIMEOUT);
    ret += InsDrv_I2c_MasterRead(s_i2c_ctrl, slave_addr|0x01, dat, len, PD_TCPC_I2C_TIMEOUT);
    
    return ret;
}

int _i2c1_send(uint8_t slave_addr, uint8_t reg_addr, uint8_t *dat, uint8_t len)
{
    uint8_t data[128] = {0};
    int ret = 0;
    
    if(len + 1 > sizeof(data))
    {
        printf("[PD] i2c send too large size!\r\n");
    }
    data[0] = reg_addr;
    memcpy(&data[1], dat, len);
    ret = InsDrv_I2c_MasterWrite(s_i2c_ctrl, slave_addr, data, len + 1, PD_TCPC_I2C_TIMEOUT);

    return ret;
}

#else

int32_t InsDrv_I2c_BAT32G157_MasterWrite(InsDrv_I2c_Ctrl_t ctrl, uint8_t addr, uint8_t *tx_buf, uint32_t tx_len, uint32_t timeout)
{
    MD_STATUS status = MD_OK;
    uint32_t ms_cnt = timeout*DATA_TRANSLATE_TIMEOUT_CNT;
    uint32_t cnt_waitstop = STOP_SIGNAL_TIMEOUT_CNT;
    uint32_t rval = 0;
    uint32_t stt_time = 0;//InsUtil_System_GetTimeStamp();

    if(ctrl.id > INSDRV_I2C_BAT32G157_ID_NUM)
    {
    	return -1;
    }

    if(ctrl.id == INSDRV_I2C0)
    {
        status = IICA0_MasterSend(addr, tx_buf, tx_len, 30);
        if(status == MD_ERROR1)
        {
            //IICA bus error
            InsDrv_I2c_BAT32G157_Reset(ctrl);
            rval = -2;
        }
        else
        {
            while(g_iica0_tx_end == 0 && ms_cnt)
            {
                delay_1us(10);
                ms_cnt --;
            }
            
            if(!ms_cnt)
            {
                rval = -3;
            }

            if(g_md_err != MD_OK)
            {
                rval = -4;
                g_md_err = MD_OK;
            }

            IICA0_StopCondition();      //send stop 
            while(0U == (IIC0->IICS0 & IICA0_IICS0_SPD_Msk))     //wait stop setup
            {
                delay_1us(10);
                cnt_waitstop--;
                if(cnt_waitstop == 0)
                {
                    rval = -5;
                    //log_i("tx wait stop failed\r\n");
                    break;
                }
            }
            if(cnt_waitstop < 30)
            {
                //log_i("tx wt sp l %d,stt:%4d\r\n", cnt_waitstop, stt_time);
            }
            //log_i("tx wait stop cnt:%d\r\n", cnt_waitstop);
        }
		//log_i("tx ms cnt = %d\r\n", timeout*DATA_TRANSLATE_TIMEOUT_CNT - ms_cnt);
	    return MD_OK;
    }
    else if(ctrl.id == INSDRV_I2C1)
    {
        status = IICA1_MasterSend(addr, tx_buf, tx_len, 30);
        if(status == MD_ERROR1)
        {
            //IICA bus error
            InsDrv_I2c_BAT32G157_Reset(ctrl);
            rval = INSERR_NG;
        }
        else
        {
            while(g_iica1_tx_end == 0 && ms_cnt)
            {
                delay_1us(10);
                ms_cnt --;
            }
            
            if(!ms_cnt)
            {
                rval = INSERR_NG;
            }

            if(g_md_err != MD_OK)
            {
                rval = INSERR_NG;
                g_md_err = MD_OK;
            }

            IICA1_StopCondition();      //send stop 
            while(0U == (IIC1->IICS1 & IICA1_IICS1_SPD_Msk))     //wait stop setup
            {
                delay_1us(10);
                cnt_waitstop--;
                if(cnt_waitstop == 0)
                {
                    rval = INSERR_NG;
                    //log_i("tx wait stop failed\r\n");
                    break;
                }
            }
            if(cnt_waitstop < 30)
            {
                //log_i("tx wt sp l %d,stt:%4d\r\n", cnt_waitstop, stt_time);
            }
            //log_i("tx wait stop cnt:%d\r\n", cnt_waitstop);
        }
		//log_i("tx ms cnt = %d\r\n", timeout*DATA_TRANSLATE_TIMEOUT_CNT - ms_cnt);
	    return rval;
    }
    return INSERR_NG;
}

int32_t InsDrv_I2c_BAT32G157_MasterRead(InsDrv_I2c_Ctrl_t ctrl, uint8_t addr, uint8_t *rx_buf, uint32_t rx_len, uint32_t timeout)
{
    MD_STATUS status = MD_OK;
    uint32_t ms_cnt = timeout*DATA_TRANSLATE_TIMEOUT_CNT;
    uint32_t cnt_waitstop = STOP_SIGNAL_TIMEOUT_CNT;
	uint32_t rval = 0;
    uint32_t stt_time = 0;//InsUtil_System_GetTimeStamp();

    if(ctrl.id > INSDRV_I2C_BAT32G157_ID_NUM)
    {
    	return -1;
    }

    if(ctrl.id == INSDRV_I2C0)
    {
        status = IICA0_MasterReceive(addr, rx_buf, rx_len, 30);

        if(status == MD_ERROR1)
        {
            //IICA bus error
            InsDrv_I2c_BAT32G157_Reset(ctrl);
            rval = -2;
        }
        else
        {
            while(g_iica0_rx_end == 0 && ms_cnt)
            {
                delay_1us(10);
                ms_cnt --;
            }
            
            if(!ms_cnt)
            {
                rval = -3;
            }

            if(g_md_err != MD_OK)
            {
                rval = -4;
                g_md_err = MD_OK;
            }

            IICA0_StopCondition();      //send stop 
            while(0U == (IIC0->IICS0 & IICA0_IICS0_SPD_Msk))     //wait stop setup
            {
                delay_1us(10);
                cnt_waitstop--;
                if(cnt_waitstop == 0)
                {
                    rval = -5;
                    //log_i("rx wait stop failed\r\n");
                    break;
                }
            }
            if(cnt_waitstop < 30)
            {
                //log_i("rx wt sp l %d,stt:%4d\r\n", cnt_waitstop, stt_time);
            }
            //log_i("rx wait stop cnt:%d\r\n", cnt_waitstop);
        }
		return MD_OK;
    }
    else if(ctrl.id == INSDRV_I2C1)
    {
        status = IICA1_MasterReceive(addr, rx_buf, rx_len, 30);

        if(status == MD_ERROR1)
        {
            //IICA bus error
            InsDrv_I2c_BAT32G157_Reset(ctrl);
            rval = INSERR_NG;
        }
        else
        {
            while(g_iica1_rx_end == 0 && ms_cnt)
            {
                delay_1us(10);
                ms_cnt --;
            }
            
            if(!ms_cnt)
            {
                rval = INSERR_NG;
            }

            if(g_md_err != MD_OK)
            {
                rval = INSERR_NG;
                g_md_err = MD_OK;
            }

            IICA1_StopCondition();      //send stop 
            while(0U == (IIC1->IICS1 & IICA1_IICS1_SPD_Msk))     //wait stop setup
            {
                delay_1us(10);
                cnt_waitstop--;
                if(cnt_waitstop == 0)
                {
                    rval = INSERR_NG;
                    log_e("rx wait stop failed\r\n");
                    break;
                }
            }
            if(cnt_waitstop < 30)
            {
                log_i("rx wt sp l %d,stt:%4d\r\n", cnt_waitstop, stt_time);
            }
            log_i("rx wait stop cnt:%d\r\n", cnt_waitstop);
        }
		return rval;
    }
    return MD_OK;
}
#endif
#endif
